import os
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask, request, g
import json
import time
from flask_cors import CORS
from flask_socketio import SocketIO
from .utils.logger import FlinkLogger

# 全局SocketIO实例
socketio = None


def create_app() -> Flask:
    app = Flask(__name__)
    app.config.setdefault("SECRET_KEY", os.environ.get("FLASK_SECRET_KEY", "flink_monitor_console_dev"))
    app.config.setdefault("JSON_AS_ASCII", False)

    # CORS
    CORS(app, resources={r"/api/*": {"origins": "*"}})

    # 设置完善的日志系统
    loggers = FlinkLogger.setup_app_logging(app)
    
    # 存储loggers到app context以便全局访问
    app.config['LOGGERS'] = loggers

    # 初始化SocketIO
    global socketio
    socketio = SocketIO(app, cors_allowed_origins="*")
    app.socketio = socketio  # 将socketio实例添加到app上下文

    # 原有Blueprints
    from .blueprints.alerts.alerts import bp as alerts_bp
    from .blueprints.alerts.alerts_extended import bp as alerts_extended_bp
    from .blueprints.flink.jobs import bp as jobs_bp
    from .blueprints.flink.jars import bp as jars_bp
    from .blueprints.flink.savepoints import bp as savepoints_bp
    from .blueprints.admin.settings import bp as settings_bp
    from .blueprints.monitoring.api_docs import bp as api_docs_bp

    app.register_blueprint(alerts_bp, url_prefix="/api/alerts")
    app.register_blueprint(alerts_extended_bp, url_prefix="/api/alerts")
    app.register_blueprint(jobs_bp, url_prefix="/api/jobs")
    app.register_blueprint(jars_bp, url_prefix="/api/jars")
    app.register_blueprint(savepoints_bp, url_prefix="/api/savepoints")
    app.register_blueprint(settings_bp, url_prefix="/api/settings")
    app.register_blueprint(api_docs_bp, url_prefix="/api/docs")

    # 新增的工具模块Blueprints
    from .blueprints.monitoring.api_listener import api_listener_bp
    from .blueprints.monitoring.kafka_monitor import kafka_monitor_bp
    from .blueprints.monitoring.kafka_forward import kafka_forward_bp
    from .blueprints.starrocks.starrocks import starrocks_bp
    from .blueprints.starrocks.starrocks_tables import starrocks_tables_bp
    from .blueprints.monitoring.callback_enhanced import bp as callback_enhanced_bp
    from .blueprints.starrocks.scheduler_management import scheduler_bp
    from .blueprints.logs.logs import logs_bp
    from .blueprints.flink.flink_cluster import bp as flink_cluster_bp
    from .blueprints.monitoring.kafka_topic_monitor import bp as kafka_topic_monitor_bp
    from .blueprints.flink.flink_monitor_config import bp as flink_monitor_config_bp
    from .blueprints.monitoring.starrocks_cluster_monitor import bp as starrocks_cluster_monitor_bp
    from .blueprints.reports.reports import reports_bp
    from .blueprints.flink.restart_history import bp as restart_history_bp
    from .blueprints.monitoring.redis_task_monitor import bp as redis_task_monitor_bp

    app.register_blueprint(api_listener_bp)
    app.register_blueprint(kafka_monitor_bp, url_prefix="/api/kafka-listener")  # Kafka数据监听服务
    app.register_blueprint(kafka_forward_bp)
    app.register_blueprint(starrocks_bp)
    app.register_blueprint(starrocks_tables_bp)
    app.register_blueprint(scheduler_bp)
    app.register_blueprint(logs_bp)
    app.register_blueprint(flink_cluster_bp)
    app.register_blueprint(kafka_topic_monitor_bp)  # Kafka Topic监控管理（已在blueprint中定义了url_prefix）
    app.register_blueprint(flink_monitor_config_bp, url_prefix="/api/flink-monitor-config")  # Flink监控配置管理
    app.register_blueprint(starrocks_cluster_monitor_bp, url_prefix="/api/starrocks-cluster-monitor")  # StarRocks集群监控管理
    app.register_blueprint(reports_bp)  # 报表管理（已在blueprint中定义了url_prefix="/api/reports"）
    app.register_blueprint(restart_history_bp, url_prefix="/api/restart-history")  # 重启历史管理
    app.register_blueprint(redis_task_monitor_bp)  # Redis监控系统（任务监控和队列监控）
    # 只注册一次callback_enhanced蓝图
    # 提供原有API: /callback, /stats, /data, /clear (供第三方使用)
    # 提供新管理API: /api/status, /api/control, /api/export (供前端管理界面使用)
    app.register_blueprint(callback_enhanced_bp)

    # 初始化回调数据
    with app.app_context():
        try:
            from .blueprints.monitoring.callback_enhanced import init_callback_data
            init_callback_data()
        except Exception as e:
            app.logger.error(f"初始化回调数据失败: {e}")
    
    # 初始化定时任务调度器（自动启动）
    if os.environ.get('FLASK_ENV') != 'testing':  # 测试环境不初始化调度器
        with app.app_context():
            try:
                from .utils.scheduler import get_scheduler, start_scheduler
                from .services.report_scheduler import init_report_scheduler, set_report_scheduler
                
                # 初始化调度器（不启动）
                scheduler = get_scheduler()
                app.logger.info("📅 定时任务调度器已初始化")
                
                # 初始化报表调度器并同步任务（init_report_scheduler 会调用 sync_all_configs，在启动前添加任务）
                report_scheduler = init_report_scheduler(scheduler)
                set_report_scheduler(report_scheduler)
                app.logger.info("📊 报表定时任务调度器已初始化并同步任务")
                
                # 启动调度器（任务会在启动后自动执行）
                # 注意：start_scheduler 现在不会重新创建调度器（除非已关闭），所以 ReportScheduler 的引用保持不变
                start_scheduler()
                
                # 确保 ReportScheduler 使用最新的调度器实例（以防万一）
                latest_scheduler = get_scheduler()
                if report_scheduler.scheduler != latest_scheduler:
                    report_scheduler.scheduler = latest_scheduler
                    set_report_scheduler(report_scheduler)
                    app.logger.info("📝 已更新 ReportScheduler 的调度器引用")
                
                app.logger.info("✅ 报表定时任务调度器已自动启动")
            except Exception as e:
                app.logger.error(f"❌ 初始化定时任务调度器失败: {e}")
                # 调度器初始化失败不应该影响主应用启动
                pass

    # 注意：kafka_monitor已重构为后台任务模式，不再使用WebSocket

    # 添加请求前后的日志中间件
    @app.before_request
    def before_request():
        """请求前处理"""
        g.start_time = time.time()
        g.request_id = f"{int(time.time() * 1000)}-{os.getpid()}"
        
        # 记录请求开始（仅对API路径）
        if request.path.startswith('/api/'):
            app.logger.info(
                f"[{g.request_id}] Request Start: {request.method} {request.path} | "
                f"IP: {request.remote_addr} | "
                f"User-Agent: {request.headers.get('User-Agent', '')[:100]}"
            )

    @app.after_request
    def after_request(response):
        """请求后处理"""
        if hasattr(g, 'start_time') and request.path.startswith('/api/'):
            duration = time.time() - g.start_time
            request_id = getattr(g, 'request_id', 'unknown')
            
            # 记录请求完成
            app.logger.info(
                f"[{request_id}] Request End: {request.method} {request.path} | "
                f"Status: {response.status_code} | "
                f"Duration: {round(duration * 1000, 2)}ms"
            )
            
            # 记录API访问日志
            FlinkLogger.log_api_request(
                endpoint=request.path,
                method=request.method,
                status_code=response.status_code,
                duration=duration
            )
        
        return response

    @app.get("/api/health")
    def health():
        """健康检查接口"""
        app.logger.info("Health check requested")
        FlinkLogger.log_business_operation(
            operation="health_check",
            details={"endpoint": "/api/health"},
            success=True
        )
        return {"status": "ok", "timestamp": time.time()}

    @app.after_request
    def standardize_response(response):
        try:
            # 仅处理JSON响应
            data = response.get_json(silent=True)
            if not isinstance(data, dict):
                return response

            # 已标准化则直接返回
            if "success" in data:
                return response

            status = response.status_code or 200
            if status >= 400:
                code_map = {400: "BAD_REQUEST", 401: "UNAUTHORIZED", 403: "FORBIDDEN", 404: "NOT_FOUND", 409: "CONFLICT", 500: "SERVER_ERROR"}
                err_code = code_map.get(status, f"HTTP_{status}")
                body = {
                    "success": False,
                    "error": data.get("error") or "Request failed",
                    "code": err_code
                }
            else:
                body = {
                    "success": True,
                    "message": data.get("message") or "ok",
                    "data": data
                }

            response.set_data(json.dumps(body, ensure_ascii=False))
            response.mimetype = "application/json"
            response.content_length = len(response.get_data())
            return response
        except Exception:
            # 避免标准化过程影响正常返回
            return response

    return app

# 导出socketio实例供run.py使用
def get_socketio():
    return socketio


